#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
using namespace std;

const int N = 100010;

int h[N];//表示堆结构
int cnt,n,m;//cnt表示堆的元素总和

void down(int u)
{
    int t = u;//t表示该节点与其‘左右儿子’中的最小值
    if(2*u<=cnt&&h[2*u]<h[t]) t = 2*u;
    if(2*u+1<=cnt&&h[2*u+1]<h[t]) t = 2*u+1;
    if(u!=t)//根节点不是最小值
    {
        swap(h[u],h[t]);
        down(t);//递归操作
    }
}
void up(int u)
{
    //如果u存在父节点并且小于父节点，交换两个数
    while(u/2&&h[u/2]>h[u])
    {
        swap(h[u/2],h[u]);
        u /=2;//下次继续从交换后的父节点开始
    }
}
int main()
{
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(false);

    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>h[i];
    cnt = n;

    for(int i=n/2;i;i--) down(i);
    while (m--)
    {
        //输出堆顶
        printf("%d ",h[1]);
        // 删除堆顶
        h[1] = h[cnt--];
        down(1);
    }
    return 0;
}